package ae.pcfc.etks.online.web.controller.admin.general.user;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.WebUtils;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate;
import ae.pcfc.etks.online.common.delegate.SecretQuestionDelegate;
import ae.pcfc.etks.online.common.delegate.UserDelegate;
import ae.pcfc.etks.online.common.vo.LabelVO;
import ae.pcfc.etks.online.common.vo.PagingVO;
import ae.pcfc.etks.online.common.vo.SCCompanyVO;
import ae.pcfc.etks.online.common.vo.SCPersonVO;
import ae.pcfc.etks.online.common.vo.SecretQuestionVO;
import ae.pcfc.etks.online.common.vo.UserVO;
import ae.pcfc.etks.online.web.ConstantsAdmin;
import ae.pcfc.etks.online.web.PageType;
import ae.pcfc.etks.online.web.ViewPath;
import ae.pcfc.etks.online.web.ViewUtils;
import ae.pcfc.etks.online.web.common.Constants;
import ae.pcfc.etks.online.web.controller.BaseController;
import ae.pcfc.etks.online.web.model.JQGridJSONModel;
import ae.pcfc.etks.online.web.model.Service;
import ae.pcfc.etks.online.web.model.UserModel;

/* $Id: AdminListServiceController 
 * Copyright (C) 2011, Trakhees
 *  
 *  History
 *
 * Date  			Author 					Remarks
 * -------------------------------------------------------------
 * May 27, 2011 	Mohtisham.Salahria 	        Created
 *
 */

/**
 * Controller that handles all {@link AdminUserController}-related requests,
 * i.e.: all requests for /admin/general/user/*
 * 
 * @author Mohtisham.Salahria
 */

@Controller
@RequestMapping(ViewPath.ADMIN_GENERAL_USER)
public class AdminUserController extends BaseController{

	private static Logger log = LoggerFactory.getLogger(AdminUserController.class);

	private Validator validator;

	// message resource
	private ResourceBundleMessageSource messageSource;

	@Resource(name = "messageSource")
	public void setMessageSource(ResourceBundleMessageSource messageSource) {
		this.messageSource = messageSource;
	}

	@Resource(name = "validator")
	public void setValidator(Validator validator) {
		this.validator = validator;
	}

	private UserDelegate userDelegate;

	@Resource(name = "userDelegate")
	public void setUserDelegate(UserDelegate userDelegate) {
		this.userDelegate = userDelegate;
	}

	private ClientRegistrationDelegate clientRegistrationDelegate;

	@Resource(name = "clientRegistrationDelegate")
	public void setClientRegistrationDelegate(ClientRegistrationDelegate clientRegistrationDelegate) {
		this.clientRegistrationDelegate = clientRegistrationDelegate;
	}

	private SecretQuestionDelegate secretQuestionDelegate;

	@Resource(name = "secretQuestionDelegate")
	public void setSecretQuestionDelegate(SecretQuestionDelegate secretQuestionDelegate) {
		this.secretQuestionDelegate = secretQuestionDelegate;
	}

	@InitBinder
	public void initBinder(WebDataBinder binder, Locale locale) {
		binder.setValidator(validator);
	}

	/**
	 * Custom handler for displaying the form, i.e.: GET requests for
	 * admin/general/service/register/list.jsp
	 * 
	 * @see WEB-INF/jsp/admin/general/user/list.jsp
	 */

	@RequestMapping(value = "/list.htm", method = RequestMethod.GET)
	public void list(@ModelAttribute(value = ConstantsAdmin.ADMIN_SHOW_SERVICE_MODEL_KEY) UserVO command) {

	}

	@ModelAttribute(ConstantsAdmin.USER_SECRETQUESTION_REQUEST_MODEL_KEY)
	public List<LabelVO> populateSecretQuestionList() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();

		LabelVO labelVO;
		List<SecretQuestionVO> secretQuestionVOs = secretQuestionDelegate.getSecretQuestionList();

		for (SecretQuestionVO secretQuestionVO : secretQuestionVOs) {
			labelVO = getMapper().map(secretQuestionVO, LabelVO.class);
			labelList.add(labelVO);

		}
		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.ADMIN_USER_LOCK_MODEL_KEY)
	public List<LabelVO> populateActionList(Locale locale) {

		List<LabelVO> labelList = new ArrayList<LabelVO>();

		LabelVO labelVO = new LabelVO();
		labelVO.setId(Constants.ACTIVE);

		labelVO.setDisplayLabel(messageSource.getMessage("label.user.unlock", null, locale));

		labelList.add(labelVO);

		labelVO = new LabelVO();
		labelVO.setId(Constants.INACTIVE);
		labelVO.setDisplayLabel(messageSource.getMessage("label.user.lock", null, locale));

		labelList.add(labelVO);

		return labelList;
	}

	/**
	 * Custom handler for displaying the form, i.e.: GET requests for
	 * admin/general/user/edit.jsp
	 * 
	 * @see WEB-INF/jsp/admin/general/user/edit.jsp
	 */

	@RequestMapping(value = "/edit.htm", method = RequestMethod.GET)
	public void edit(@RequestParam(value = "userId", required = true) String userId,
			@ModelAttribute(value = ConstantsAdmin.ADMIN_UPDATE_USER_MODEL_KEY) UserModel userModel, Model model, Locale locale) {

		UserVO userVO = this.userDelegate.findUserByPrimaryKey(Long.valueOf(userId));

		if (userVO != null) {
			getMapper().map(userVO, userModel);

			if (!(userVO.getStrType().equals(Constants.ADMIN))) {
				String trakheesId = userVO.getStrTrakheesId();
				String[] client = trakheesId.split("-");

				if (client[0].equals(Constants.COMPANY)) {
					SCCompanyVO scCompanyVO = clientRegistrationDelegate.findSCCompanyByTrakheesId(trakheesId);
					model.addAttribute(ConstantsAdmin.CLIENT_COMPANY_REGISTER_SUMMARY_REQUEST_MODEL_KEY, scCompanyVO);
				} else if (client[0].equals(Constants.PERSON)) {
					SCPersonVO scPersonVO = clientRegistrationDelegate.findSCPersonByTrakheesId(trakheesId);
					model.addAttribute(ConstantsAdmin.CLIENT_PERSON_REGISTER_SUMMARY_REQUEST_MODEL_KEY, scPersonVO);
				}
			}
			Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			String userName;
			if (principal instanceof UserDetails) {
				userName = ((UserDetails) principal).getUsername();
			} else {
				userName = principal.toString();
			}
			if (userModel.getStrStatus().equals(Constants.INACTIVE)) {
				userModel.setStrAccountStatus(messageSource.getMessage("label.user.locked", null, locale));
			} else
				userModel.setStrAccountStatus(messageSource.getMessage("label.user.active", null, locale));

			userModel.setStrActionBy(userName);
			userModel.setStrStatusAction(userVO.getStrStatus());

		}

	}

	/**
	 * Custom handler for displaying the form, i.e.:POST requests for
	 * admin/general/user/edit.jsp
	 * 
	 * @see #form(UserModel)
	 * @see WEB-INF/jsp/admin/general/user/edit.jsp
	 */

	@RequestMapping(method = RequestMethod.POST, value = "/edit.htm")
	public String edit(HttpServletRequest request, SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.ADMIN_UPDATE_USER_MODEL_KEY) @Valid UserModel userModel, BindingResult errors, Locale locale) {

		boolean isSave = WebUtils.hasSubmitParameter(request, ConstantsAdmin.SUBMIT_BUTTON);

		if (isSave) {
			if (errors.hasErrors()) {

				return ViewUtils.DEFAULT_VIEW;

			} else {

				String[] messageArgs = new String[] { messageSource.getMessage("success.user.info.edit", null,
						RequestContextUtils.getLocale(request)) };
				
				if(userModel.getStrType().equals(Constants.ADMIN))
				{
					
					errors.reject("error.user.admin.edit", messageArgs, null);
					return ViewUtils.DEFAULT_VIEW;
				}
				
				UserVO userVO = new UserVO();

				getMapper().map(userModel, userVO);
				userVO.setStrStatus(userModel.getStrStatusAction());
				this.userDelegate.lockUser(userVO);
				
				Map<String, String> paramMap = new HashMap<String, String>();
				paramMap.put("userId", userModel.getlUserId().toString());
				//paramMap.put(Constants.SUCCESS_PARAM, messageSource.getMessage("success.user.info.edit", null, locale));
				request.setAttribute(ConstantsAdmin.SUCCESS_PARAM, messageSource.getMessage("success.user.info.edit", null, locale));
				//return ViewUtils.getForward(ViewPath.ADMIN_GENERAL_USER, PageType.EDIT, paramMap);
				return ViewUtils.getForward(ViewPath.ADMIN_GENERAL_USER, PageType.LIST);
			}

		}
		
		return ViewUtils.getRedirect(ViewPath.ADMIN_GENERAL_USER, PageType.LIST);
		
	}
	/**
	 * Custom handler for getting grid model, i.e.:Requests for
	 * admin/general/user/displayUserTable
	 * 
	 * @see WEB-INF/jsp/admin/general/user/displayUserTable
	 */
	@RequestMapping(value = "/displayUserTable")
	public @ResponseBody
	JQGridJSONModel displayServicesTable(HttpServletRequest request, @RequestParam(value = "page", required = true) String page,
			@RequestParam(value = "rows", required = true) String rows,
			@RequestParam(value = "sidx", required = true) String sidx,
			@RequestParam(value = "sord", required = true, defaultValue = "desc") String sord,
			@RequestParam(value = "_search", required = false) String isSearch,
			@RequestParam(value = "searchField", required = false) String searchField,
			@RequestParam(value = "searchOper", required = false) String searchOper,
			@RequestParam(value = "searchString", required = false) String searchString,
			Locale locale) {

		List<String> requestParameterNames = Collections.list((Enumeration<String>) request.getParameterNames());

		for (String parameterName : requestParameterNames) {
			System.out.println("parameterName = " + parameterName);

		}

		System.out.println("page==" + page);
		System.out.println("rows==" + rows);
		System.out.println("sidx==" + sidx);
		System.out.println("searchField==" + searchField);
		System.out.println("searchOper==" + searchOper);
		System.out.println("searchString==" + searchString);
		System.out.println("isSearch==" + isSearch);
		System.out.println("sord==" + sord);

		JQGridJSONModel result = new JQGridJSONModel();

		Integer pageIndx = 1, count = this.userDelegate.getUserList().size(), totalpages = 0, start = 0;
		Integer limit = 40;
		try {
			pageIndx = Integer.parseInt(page);
		} catch (Exception nullexp) {
			pageIndx = 1;
		}
		try {
			limit = Integer.parseInt(rows);
		} catch (Exception nullexp) {
			pageIndx = 10;
		}

		if (count > 0)
			totalpages = (int) Math.ceil(((float) count) / (float) limit);
		else
			totalpages = 0;

		if (pageIndx > totalpages)
			pageIndx = totalpages;

		start = (limit * pageIndx) - limit;
		result.setPage(pageIndx.toString());
		result.setRecords(count + "");
		result.setTotal(totalpages + "");
		log.info("Page=" + pageIndx + " , Records=" + limit + " , Total=" + totalpages);
		
		PagingVO pagingVO = new PagingVO();
		pagingVO.setStart(start);
		pagingVO.setSearchfieldName(searchField);
		pagingVO.setSerachString(searchString);
		pagingVO.setSortFieldName(sidx);
		pagingVO.setSortOrder(sord);
		pagingVO.setPageNumber(pageIndx);
		pagingVO.setPageSize(limit);
		
		List<UserVO> userVOs = this.userDelegate.getUserListByPagingParameters(pagingVO);
		if(userVOs != null){
			for (UserVO userVO : userVOs) {
				List<String> cells = new ArrayList<String>();
				cells.add(userVO.getlUserId().toString());
				cells.add(userVO.getStrUserName());
				cells.add(userVO.getStrUserNameArab());
				cells.add(userVO.getStrEmail());
				if(ConstantsCommon.ADMIN.equals(userVO.getStrType())){
					cells.add(messageSource.getMessage("user.admin", null, locale));
				}else if(ConstantsCommon.COMPANY_ADMIN.equals(userVO.getStrType())){
					cells.add(messageSource.getMessage("user.client.admin", null, locale));
				}else if(ConstantsCommon.COMPANY_EMPLOYEE.equals(userVO.getStrType())){
					cells.add(messageSource.getMessage("user.company.employee", null, locale));
				}else if(ConstantsCommon.INTERNAL_TRAKHEES_STAFF.equals(userVO.getStrType())){
					cells.add(messageSource.getMessage("user.internal.staff", null, locale));
				}else{
					cells.add("");
				}
				cells.add(userVO.getStrStatus().equals(Constants.ACTIVE) ? ConstantsAdmin.STATUS_ACTIVE : ConstantsAdmin.STATUS_INACTIVE);
				result.addRows(userVO.getlUserId().toString(), cells);
			}
		}
		
		return result;

	}

	/**
	 * Custom handler for displaying the form, i.e.:POST requests for
	 * admin/general/user/list.jsp
	 * 
	 * @see #form(Service)
	 * @see WEB-INF/jsp/admin/general/user/list.jsp
	 */

	@RequestMapping(method = RequestMethod.POST, value = "/list.htm")
	public String list(HttpServletRequest request, SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.ADMIN_SHOW_SERVICE_MODEL_KEY) @Valid Service listService, BindingResult errors) {

		boolean isSave = WebUtils.hasSubmitParameter(request, ConstantsAdmin.SAVE_BUTTON);

		if (isSave) {
			if (errors.hasErrors()) {

				return ViewUtils.DEFAULT_VIEW;

			} else {

				String[] messageArgs = new String[] { messageSource.getMessage("success.user.info.edit", null,
						RequestContextUtils.getLocale(request)) };

			}

		}
		return ViewUtils.DEFAULT_VIEW;
	}

}
